﻿import kliment.utils._Type;
/**
 * ...
 * @author	Kliment
 * @version	1.1.0
 */
class kliment.data.serialization.json.JSONEncoder extends String {
	
	public function JSONEncoder(value) {
		super(_convertToString(value))
	}
	
	private function _convertToString(value):String {
		switch (typeof(value)) {
			case _Type.OBJECT:
				if (value) {
					if (_Type.isArray(value)) 
						return _arrayToString(value);
					return _objectToString(value);
				}
				return _Type.NULL;
			break;
			
			case _Type.NUMBER: return isFinite(value)?String(value):'null'; break;
			
			case _Type.STRING: return _escapeString(value); break;
			
			case _Type.isBoolean: return String(value); break;
			
			default: return _Type.NULL; break;
		}
	}
	
	private function _arrayToString(value:Array):String {
		var str:String = '';
		var val;
		var length:Number = value.length;
		for (var i:Number = 0; i < length; ++i) {
			val = _convertToString(value[i]);
			if (str) 
				str += ',';
			str += val;
		}
		return '[' + str + ']';
	}
	
	private function _objectToString(value:Object):String {
		var str:String = '';
		var val;
		for (var i in value) {
			val = value[i];
			if (!_Type.isUndefined(val) && !_Type.isFunction(val)) {
				val = _convertToString(val);
				if (str) 
					str += ',';
				str += _convertToString(i) + ':' + val;
			}
		}
		return '{' + str + '}';
	}
	
	private function _escapeString(value:String):String {
		var length:Number = value.length;
		var str = '';
		var char;
		for (var i:Number = 0; i < length; ++i) {
			char = value.charAt(i);
			if (char >= ' ') {
				if (char == '\\' || char == '"') 
					str += '\\';
				str += char;
			} else {
				switch (char) {
					case '\b': str += '\\b'; break;
					case '\f': str += '\\f'; break;
					case '\n': str += '\\n'; break;
					case '\r': str += '\\r'; break;
					case '\t': str += '\\t'; break;
					default: 
						char = char.charCodeAt();
						str += '\\u00' + Math.floor(char / 16).toString(16) + (char % 16).toString(16);
					break;
				}
			}
		}
		return '"' + str + '"';
	}
}